/* 
 * File:   DarkFiber.cpp
 * Author: ja1e09
 *
 * Created on July 27, 2011, 12:54 AM
 */

#include "DarkFiber.h"

const bool MPI_Init()
{
    MPI::Status mpiStatus;

    // Start MPI
    MPI::Init();

    // Check Init
    // return false;

    // Get Communicator Size
    int iRank = MPI::COMM_WORLD.Get_rank();

    // Inform the Console of out rank
    Console::GetInstance()->SetRank(iRank);

    // Get the size of the cluster
    int iClusterSize = MPI::COMM_WORLD.Get_size();

    // Add Cluster Size to Config
    Config::GetInstance()->AddIntToMap("iClusterSize", iClusterSize);

    int iOMPMaxThreads = omp_get_max_threads();

    // Add Max Threads to config
    Config::GetInstance()->AddIntToMap("iOMPMaxThreads", iOMPMaxThreads);

    std::ostringstream ssLogMsg;
    ssLogMsg << "DarkFiber::Running in " << iClusterSize << " nodes with " << iOMPMaxThreads << " threads per node.";
    Console::GetInstance()->Add(ssLogMsg.str());

    return true;
}

const bool MPI_Init_Topo()
{
    // Fetch the cluster size from config
    int iClusterSize = Config::GetInstance()->GetInt("iClusterSize");

    // Compute the Number of Agents in the Simulation
    int iNumAgents = iClusterSize - 1;
    if (iNumAgents < 1)
    {
        std::ostringstream ssLogMsg;
        ssLogMsg << "MPI_Init_Topo::ERROR::Insufficient number of nodes: " << iClusterSize << " Check PBS Script. Aborting ... ";
        Console::GetInstance()->Add(ssLogMsg.str());
        return false;
    }
    
    // Add iNumAgents to Config
    Config::GetInstance()->AddIntToMap("iNumAgents",iNumAgents);

    // Create the MPI Star Graph

    std::ostringstream ssLogMsg;
    ssLogMsg << "MPI_Init_Topo::Star Topology with " << iNumAgents << " created.";
    Console::GetInstance()->Add(ssLogMsg.str());

    return true;
}

void End(const bool bFailed)
{
    // End MPI
    MPI::Finalize();

    if (bFailed)
        Console::GetInstance()->Add("DarkFiber::Ended with errors.");
    else
        Console::GetInstance()->Add("DarkFiber::Ended normally.");

    // Clean Console
    Console::GetInstance()->Destroy();
}

int main()
{
    // Init Basic MPI Stuff
    if (!MPI_Init())
    {
        End(true);
        return -1;
    }

    // Load XML Config in all the nodes
    Config::GetInstance()->Init();

    // Create the Star Topology
    if (!MPI_Init_Topo())
    {
        End(true);
        return -1;
    }

    // Star Split
    if (Config::GetInstance()->GetInt("iRank") == 0)
    {
        // We are the World 
        CWorld::GetInstance()->Run();
    }
    else
    {
        // We are the Agents
        CAgent *pAgent=new CAgent(MPI::COMM_WORLD.Get_rank());
        pAgent->Run();
        SAFE_DELETE(pAgent);
    }

    End(false);
    return 0;
}

